<template lang="html">
  <article
    id="views-index"
    :class="[isHorizontalMoving || isLockIndexContainer? 'isLock':'isScroll']"
    @touchstart="indexTouchstart"
    @touchmove="indexTouchmove"
  >

    <div class="index-banner-wrapper">
      <Banner :banners="banners"></Banner>
    </div>

    <div class="index-main-wrapper">

      <div class="main-options">
        <div class="options-classify-wrapper">
          <Classify
            :district="district"
            :category="category"
            v-on:setCurrentDistrict="setCurrentDistrict"
            v-on:setCurrentCategory="setCurrentCategory"
          ></Classify>
        </div>
        <div class="options-datePicker-wrapper">
          <DatePicker
            :dates="dateObjs"
          ></DatePicker>
        </div>
        <p class="options-currentDay-wrapper">
          {{currentDay ? currentDay : '最近活动'}}
        </p>
      </div>

      <PullRefresh
        :isLock="isPullRefreshLock"
        :onRefresh="refreshList"
      >
        <div
          id="content-container"
          class="main-content"
          :style="{ height: `${this.screenHeight - this.pickerEleHeight}px`}"
          :class="[isHorizontalMoving || isLockContentContainer? 'isLock':'isScroll']"
          @touchstart="contentTouchstart"
          @touchmove="contentTouchmove"
          @touchend="contentTouchend"
        >
          <ul
            class="content-wrapper"
            :style="{ transform: `translate3d(${deltaX}px,0,0)`, transition: `transform linear ${transitionX}s`}"
          >
            <li
              class="content-item"
              v-for="(courseList, index) in courseCollection">
              <div class="content-counter-wrapper" v-if="isShowCounter">
                <Counter
                  :counterData="counterData"
                  v-if="index <= 1"
                ></Counter>
              </div>
              <div class="content-list-wrapper">
                <List
                  :courseList="courseList"
                  :currentDistrictId="currentDistrictId"
                  :currentCategoryId="currentCategoryId"
                ></List>
              </div>
            </li>
          </ul>
        </div>
      </PullRefresh>

    </div>

  </article>
</template>

<script>
// import evtBus from '@/components/evtbus--index-pull_refresh'
import superagent from 'superagent'
import objectAssign from 'object-assign'
import _dayString from '@/constant/day_string'
import authMiddleWare from '@/lib/auth-middleware'

export default {
  name: 'PageIndex',
  components: {
    Banner: require('@/components/index_banner'),
    Classify: require('@/components/index_classify'),
    DatePicker: require('@/components/index_date_picker'),
    Counter: require('@/components/index_counter'),
    List: require('@/components/index_list/index'),

    PullRefresh: require('@/components/common_pull_refresh/'),
  },
  data(){
    return {
      isHorizontalMoving: false,//锁定水平操作
      // isVerticalMoving: false,//锁定纵向操作
      /*
      水平滑动操作相关
       */
      contentStartPosition: {
         X:0,
         Y:0
       },
      contentOffset: null,
      deltaX: 0,
      transitionX: 0.2,
      /*
      纵向滑动操作相关
       */
      startPosition: {
        X:0,
        Y:0
      },
      screenWidth: 0,
      screenHeight: 0,
      indexContainerEle: null,//主容器元素
      contentContainerEle: null,//内容容器元素
      pickerEleHeight: null,//分类选择与日期选择器元素
      indexScrollMax: 0,//主容器滚动至顶阈值
      isLockIndexContainer: false,//是否锁定主容器滑动
      isLockContentContainer: true,//是否锁定内容容器滑动（课程列表）
      /*
      下拉刷新相关
       */
      isPullRefreshLock: true,
      /*
      DatePicker相关
       */
      dateObjs: null,
      /*
      倒计时相关
       */
      isShowCounter: true,
      counterData: null,
      counterTimer: null,
      /*
      分类相关
       */
      district: [],
      category: [],
      // currentDistrictId: 0,
      // currentCategoryId: 0,
      dayCount: 7,//显示最近课程的天数
      courseCollection: null,//课程+活动列表
      banners: [],
    }
  },
  computed: {
    currentIndex(){
      return this.$store.state.indexData.currentIndex
    },
    currentDay(){
      if(this.currentIndex == 0) return false
      let obj = this.dateObjs[this.currentIndex - 1]
      return `${obj.year}年${obj.month}月${obj.date}日  ${obj.dayString.ch}`
    },
    currentDistrictId(){
      return this.$store.state.indexData.currentDistrictId
    },
    currentCategoryId(){
      return this.$store.state.indexData.currentCategoryId
    },
  },
  watch: {
    currentIndex(val){
      this.deltaX = this.currentIndex * -1 * this.screenWidth
    },
  },
  methods: {
    /**
     * 纵向滑动相关
     */
    indexTouchstart(e){
      this.startPosition.X = e.touches[0].clientX
      this.startPosition.Y = e.touches[0].clientY
    },
    indexTouchmove(e){
      let curY = e.touches[0].clientY,
          curX = e.touches[0].clientX,
          offsetX = curX - this.startPosition.X,
          offsetY = curY - this.startPosition.Y,
          isUpDirection = offsetY < 0

      if(!this.isPullRefreshLock) return //下拉刷新未完成则返回

      if(isUpDirection){
        let isIndexBottom = this.indexContainerEle.scrollTop >= this.indexScrollMax

        if(!this.isLockIndexContainer && isIndexBottom){//主容器已滚动至刚好覆盖banner
          console.log('主容器滚动至顶');
          this.isLockIndexContainer = true
          this.isLockContentContainer = false
          //TODO:上拉加载改为点击加载更多
        }
      } else {
        let isContentUpper = this.contentContainerEle.scrollTop === 0,
            isIndexUpper = this.indexContainerEle.scrollTop === 0

        if(this.isLockIndexContainer && isContentUpper){
          console.log('内容容器已滚动至顶，并解锁内容容器');
          this.isLockIndexContainer = false
          this.isLockContentContainer = true
        } else if(isContentUpper && isIndexUpper && offsetY > 0.1*this.screenWidth && offsetX < 0.1*this.screenWidth){//内外容器均滚动至顶则判断是否下拉刷新
          console.log('下拉刷新');//TODO:添加下拉刷新功能
          e.preventDefault()
          this.isPullRefreshLock = false
        }
      }
    },
    /*
    横向滑动相关
     */
    contentTouchstart(e){
      this.contentStartPosition.X = e.touches[0].clientX
      this.contentStartPosition.Y = e.touches[0].clientY
    },
    contentTouchmove(e){
      let curX = e.touches[0].clientX,
          offsetX = curX - this.contentStartPosition.X

      if(this.isHorizontalMoving || Math.abs(offsetX) > 0.1*this.screenWidth){//横向滑动大于临界点或横向滑动已开始时
        console.log('水平滑动操作');
        e.preventDefault()
        this.transitionX = 0
        let previousDeltaX = this.currentIndex * -1 * this.screenWidth
        this.isHorizontalMoving = true//锁定水平滑动过程，待完成后才判断是否能进行纵向滚动操作
        this.deltaX = previousDeltaX + offsetX
      }
    },
    contentTouchend(e){
      this.transitionX = 0.2
      let isRightDirection = false,
          previousDeltaX = this.currentIndex * -1 * this.screenWidth,
          offsetX = this.deltaX - previousDeltaX
      if(offsetX > 0){
        isRightDirection = true
      }
      if(this.isPullRefreshLock && this.isHorizontalMoving && Math.abs(offsetX) > 0.25*this.screenWidth){//滑动距离超过临界点，触发翻页
        this.turnPage(isRightDirection)
        .then(result => {
          if(!result){
            this.deltaX = previousDeltaX//不进行翻页则回滚
          }
        })
        .catch(e => {
          this.deltaX = previousDeltaX//不进行翻页则回滚
          console.warn(e)
        })
      } else {
        this.deltaX = previousDeltaX//不进行翻页则回滚
      }
      this.isHorizontalMoving = false//解锁水平滑动
    },
    turnPage(isRightDirection){
      return new Promise((resolve, reject) => {
        if(isRightDirection){
          if(this.currentIndex === 0) {
            resolve(false)
          } else {
            this.$store.dispatch('setCurrentIndex', this.currentIndex - 1)
            resolve(true)
          }
        } else {
          if(this.currentIndex === this.dayCount){
            resolve(false)
          } else {
            this.$store.dispatch('setCurrentIndex', this.currentIndex + 1)
            resolve(true)
          }
        }
      })
    },
    /**
     * 数据逻辑
     */
    refreshList(){
      return new Promise((resolve, reject) => {
        //NOTICE:1.开始请求时必须设置Loading蒙层避免进一步的交互操作 2.注意接口刷新完成之后必须设置锁定PullRefresh
        this.$store.dispatch('toggleIsLoading')
        this.getListByIndex(this.currentIndex)
        .then(courseList => {
          this.courseCollection.splice(this.currentIndex, 1, courseList)
          this.isPullRefreshLock = true
          this.$store.dispatch('toggleIsLoading')
          resolve()
        })
      })
    },
    getListByIndex(index){
      return new Promise((resolve, reject) => {
        if(index > 0){
          let dateObj = this.dateObjs[index - 1],
              // startDate = `2017-03-14`//TODO: test
              startDate = `${dateObj.year}-${dateObj.month}-${dateObj.date}`
          this.getCourseList(startDate, 1)
          .then(result => {
            if(!result.subjectsByDateRange[0]){
              resolve()
            } else {
              let courseList = this.dailyCourseListHelper(result.subjectsByDateRange[0], index-1)
              resolve(courseList)
            }
          })
          .catch(e => {
            console.log(e);
          })
        } else if(index == 0){
          this.getEventList()
          .then(result => {
            resolve(this.eventListHelper(result))
          })
          .catch(e => {
            console.log(e);
          })
        } else {
          reject(new Error('getListByIndex: index error'))
        }
      })
    },
    getDeadline(){
      return new Promise((resolve, reject) => {
        superagent.get('/api/subject/countdown')
          .use(authMiddleWare())
          .end((err, res) => {
            if(res.ok){
              resolve(res.body.data)
            } else {
              if(!!res.body.data){
                resolve(res.body.data)
              } else {
                reject(new Error('getDeadline error'))
              }
            }
          })
      })
    },
    formatDeadline(deadline = 1494490860000){//TODO:test
      return new Promise((resolve, reject) => {
        let remaining = deadline - Date.now(),
            millsec = 36e5,
            a_hours = remaining/millsec,
            hours = Math.floor(a_hours) + '',
            a_mins = (a_hours - hours) * 60,
            mins = Math.floor(a_mins) + '',
            secs = Math.floor((a_mins - mins) * 60) + ''

        if(remaining <= 0){
          reject(new Error('deadline is ahead of Date.now'))
        } else {
          if(mins < 10){
            mins = '0' + mins
          }
          if(secs < 10){
            secs = '0' + secs
          }
          resolve({
            hours,
            mins,
            secs,
            remaining
          })
        }
      })
    },
    countDownHandler(data){
      function addZero(num){
        if(num >= 10){
          return num + ''
        } else {
          return '0' + num
        }
      }
      function counter({ hours, mins, secs }){
        if(secs == 0){
          secs = '59'
          if(mins == 0){
            mins = '59'
            if(hours == 0){
              return false
            } else {
              hours--
            }
          } else {
            mins--
          }
        } else {
          secs--
        }
        hours = hours + ''
        mins = addZero(mins)
        secs = addZero(secs)
        return {
          hours,
          mins,
          secs
        }
      }
      if(!this.counterTimer){
        this.counterTimer = window.setInterval(() => {
          let result = counter(this.counterData)
          if(!result){
            clearInterval(this.counterTimer)
            return
          }
          this.counterData.hours = result.hours
          this.counterData.mins = result.mins
          this.counterData.secs = result.secs
        }, 1000)
      }
    },
    getCourseList(startDate = '2017-03-14', dateRange = 7){
      return new Promise((resolve, reject) => {
        superagent.post('/api/subject/ajax')
          .use(authMiddleWare())
          .query({
            startDate,
            dateRange
          })
          .end((err, res) =>{
            if(res.ok){
              resolve(res.body.data)
            } else {
              reject(err)
            }
          })
      })
    },
    getEventList(){
      return new Promise((resolve, reject) => {
        superagent.post('/api/subject/activity')
          .use(authMiddleWare())
          .end((err, res) => {
            if(res.ok){
              resolve(res.body.data.records)
            } else {
              reject(err)
            }
          })
      })
    },
    getBanners(){
      return new Promise((resolve, reject) => {
        superagent.get('/api/banner/index')
          .use(authMiddleWare())
          .end((err, res) => {
            if(res.ok){
              resolve(res.body.data)
            } else {
              reject(new Error('getBanners error'))
            }
          })
      })
    },
    /**
     * [categoryMapHelper]
     * @method categoryMapHelper
     * @param  {Object}          category [分类菜单]
     * @return {Array}                   [返回具有组件所约定的数据结构的分类菜单]
     */
    categoryMapHelper(category){
      let result = []
      Object.keys(category).forEach(key => {
        let resultItem = {
          id: category[key].categoryId,
          value: `${category[key].categoryName}（${category[key].categoryRemark}）`
        }
        result.push(resultItem)
      })
      result.unshift({
        id: 0,
        value: '所有课程'
      })
      return result
    },
    /**
     * [districtMapHelper]
     * @method districtMapHelper
     * @param  {Object}          districts [地址菜单]
     * @return {Array}                   [返回具有组件所约定的数据结构的地址菜单]
     */
    districtMapHelper(districts){
      let result = []
      Object.keys(districts).forEach(key => {
        let resultItem = {
          id: key,
          value: districts[key]
        }
        result.push(resultItem)
      })
      result.unshift({
        id: 0,
        value: '所有区域'
      })
      return result
    },
    /**
     * 分类相关
     */
     setCurrentDistrict(id){
       this.$store.dispatch('setCurrentDistrictId', parseInt(id, 10))
     },
     setCurrentCategory(id){
       this.$store.dispatch('setCurrentCategoryId', parseInt(id, 10))
     },
    /**
     * [eventListHelper]
     * @method eventListHelper -- 生成日期字符串；生成isEnd字段并分选出已结束课程
     * @param  {Array}        eventList [活动列表]
     * @return {Array}                  [新的活动列表]
     */
    eventListHelper(eventList){
      let endEvents = [], normalEvents = []
      eventList.map(item => {
        let startTime = new Date(item.startTime * 1000)
        item.dateStr = `${startTime.getMonth() + 1}月${startTime.getDate()}日`
        item.isEnd = Date.now() > item.endTime*1000
        if(item.isEnd){
          endEvents.push(item)
        } else {
          normalEvents.push(item)
        }
      })
      return normalEvents.concat(endEvents)
    },
    /**
     * [courseCollectionHelper description]
     * @method courseCollectionHelper
     * @param  {[type]}          courseCollection [description]
     * @return {[type]}                           [description]
     */
    courseCollectionHelper(courseCollection){
      for(let i = 0;i < courseCollection.length;i++){
        if(courseCollection[i]){
          courseCollection[i] = this.dailyCourseListHelper(courseCollection[i],i)
        }
      }
      return courseCollection
    },
    /**
     * [dailyCourseListHelper 处理每日的课程列表--分选出已结束课程并将之归为一块]
     * @method dailyCourseListHelper
     * @param  {[type]}              courseList [description]
     * @return {[type]}                         [description]
     */
    dailyCourseListHelper(courseList, index){
      let dateObj = this.dateObjs[index],
          nowTime = Date.now(),
          endCourses = {
            dateStr: `${dateObj.month}月${dateObj.date}日`,
            name: '已结束',
            store: []
          }
      if(!courseList) return courseList
      for(let k in courseList){
        let newStore = []
        courseList[k].dateStr = `${dateObj.month}月${dateObj.date}日`
        for(let i = 0; i < courseList[k].store.length;i++){
          let item = objectAssign({}, courseList[k].store[i])
          item.isEnd = nowTime > item.endTime*1000
          if(item.isEnd){
            endCourses.store.push(item)
            // courseList[k].store.splice(i, 1)
          } else {
            newStore.push(item)
          }
        }
        courseList[k].store = newStore
      }
      courseList['01'] = endCourses
      return courseList
    },
  },
  beforeMount(){
    this.screenWidth = window.innerWidth
    this.screenHeight = window.innerHeight
    this.deltaX = -this.screenWidth*this.currentIndex//初始化内容容器位移
  },
  created(){
    function generateDateObjs(size){
      let days = [],
          nowDate = new Date().getDate()
      for(let i = 0; i < size;i++){
        let cur = new Date(new Date().setDate(nowDate + i))
        days.push({
          year: cur.getFullYear(),
          month: cur.getMonth() + 1,
          date: cur.getDate(),
          day: cur.getDay(),
          dayString: {
            en: _dayString['en'][cur.getDay()],
            ch: _dayString['ch'][cur.getDay()]
          }
        })
      }
      return days
    }
    this.dateObjs = generateDateObjs(this.dayCount)
    //倒计时相关
    this.getDeadline()
    .then(data => {
      if(!data || !data.startTime) {
        throw new Error('cannot getDeadline')
      }
      let deadline = parseInt(data.startTime, 10) * 1000
      return this.formatDeadline(deadline)
    })
    .then(counterData => {
      this.counterData = counterData
      this.countDownHandler(this.counterData)
    })
    .catch(e => {
      if(e.message === 'deadline is ahead of Date.now'){
        this.isShowCounter = false
      }
    })
    // 获取课程列表
    let dateObj = this.dateObjs[0],
        startDate = `${dateObj.year}-${dateObj.month > 9 ? dateObj.month : `0${dateObj.month}`}-${dateObj.date}`
    Promise.all([this.getCourseList(startDate, this.dayCount), this.getEventList()])
    .then(results => {
      let courseList = this.courseCollectionHelper(results[0].subjectsByDateRange),
          eventList = this.eventListHelper(results[1]),
          courseCollection = []
      courseCollection = courseList.slice(0)
      courseCollection.unshift(eventList)
      this.courseCollection = courseCollection

      this.district = this.districtMapHelper(results[0].cities)
      this.category = this.categoryMapHelper(results[0].categories)
    })
    //获取banners
    this.getBanners()
    .then(banners => {
      this.banners = banners
    })
  },
  mounted(){
    const el = this.$el
    this.indexContainerEle = el
    this.contentContainerEle = el.querySelector('#content-container')
    this.pickerEleHeight = el.querySelector('.main-options').offsetHeight
    this.indexScrollMax = el.querySelector('.index-banner-wrapper').offsetHeight
  },
}
</script>

<style lang="scss" scoped>
@import "../css/config";
$options-height: 235px;
.willChangeTrans{
  will-change: transform;
}
.isScroll{
  overflow-x: hidden;
  overflow-y: scroll!important;
}
.isLock{
  overflow-x: hidden;
  overflow-y: hidden!important;
}
#views-index{
  width: 100%;
  height: 100%;
  background-color: $common-bg;
  overflow: scroll;
  box-sizing: border-box;
  padding-bottom: $tablist-height;
  .index-banner-wrapper{
    width: 100%;
    height: 215px;
  }
  .index-main-wrapper{
    position: relative;
    width: 100%;
    height: 100%;
    box-sizing: border-box;
    padding-top: $options-height;
    .main-options{
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: $options-height;
      display: flex;
      flex-direction: column;
      justify-content: space-between;
      .options-classify-wrapper{
        margin: 20px 0 15px;
        width: 100%;
      }
      .options-datePicker-wrapper{
        width: 100%;
      }
      .options-currentDay-wrapper{
        display: block;
        height: 40px;
        font-size: 25px;
        font-weight: 100;
        color: #e2e2e2;
        box-sizing: border-box;
        padding: 0 20px;
      }
    }
    .main-content{
      width: 100%;
      height: 100%;//TODO:滚动控制点
      overflow: hidden;
      .content-wrapper{
        display: inline-block;
        min-width: 100%;
        height: 100%;
        font-size: 0;
        background-color: #202020;
        white-space: nowrap;
        .content-item{
          position: relative;
          display: inline-block;
          width: 750px;
          height: 100%;
          overflow: scroll;
          .content-counter-wrapper{
            margin-top: 20px;//TODO: test
            width: 100%;
          }
          .content-list-wrapper{
            width: 100%;
          }
        }
      }
    }
  }
}
</style>
